﻿using System.Collections.Generic;
using System.Threading.Tasks;

using CalciumTemplateApp.ApplicationModel;
using CalciumTemplateApp.UI.Settings;

using Outcoder;
using Outcoder.ComponentModel;
using Outcoder.Messaging;
using Outcoder.Services;
using Outcoder.UserOptionsModel;
using Outcoder.UserOptionsModel.UserOptions;

namespace CalciumTemplateApp
{
	/// <summary>
	/// This class contains strongly typed setting properties, 
	/// and is used to initialize the user options that are displayed on the app's 
	/// options view.
	/// Add your own options to the options collection in the InitializeUserOptions method.
	/// </summary>
	public class AppSettings : ObservableObject, IMessageSubscriber<SettingChangeEventArgs>
	{
		readonly ISettingsService settingsService = Dependency.Resolve<ISettingsService>();
		static bool userOptionsInitialized;

		public static void InitializeUserOptions()
		{
			if (userOptionsInitialized)
			{
				return;
			}
			userOptionsInitialized = true;

			var userOptionsService = Dependency.Resolve<IUserOptionsService>();

			var defaultCategory = new OptionCategory(
							"General", () => Strings.Options_Categories_General);

			/* Add options to the following collection and they will be 
			 * automatically displayed on the options page. 
			 * Each UserOption object must have a unique key. 
			 * Lambda expression are used for most of the properties 
			 * to allow your app to switch languages without requiring a restart. 
			 * You can specify a template for the option by setting its TemplateFunc property.
			 * See the UserOptionBase implementations. */
			List<IUserOption> generalOptions = new List<IUserOption>
					{
						new BooleanUserOption(() => Strings.Options_SystemTrayVisible_Title, SystemTrayVisibleKey, () => systemTrayVisibleDefaultValue),
						//new BooleanUserOption(() => Strings.Options_RunUnderLockScreen_Title, LockScreenService.RunningEnabledSettingsKey, () => false),
						/* *** Add options here *** */
						//new StringUserOption(() => "Name", "ExampleString1", () => "Katka", "Url"),
			        };

			var advancedCategory = new OptionCategory(
							"Advanced", () => Strings.Options_Categories_Advanced);

			List<IUserOption> advancedOptions = new List<IUserOption>
					{
						new BooleanUserOption(() => Strings.Options_ConfirmAppClose_Title, ConfirmAppClose, () => confirmAppCloseDefaultValue),
			        };

			userOptionsService.Register(generalOptions, defaultCategory);
			userOptionsService.Register(advancedOptions, advancedCategory);
		}

		public MainViewSettings MainViewSettings => Dependency.Resolve<MainViewSettings, MainViewSettings>();

		const string SystemTrayVisibleKey = "SystemTrayVisible";
		static bool systemTrayVisibleDefaultValue = true;

		public bool SystemTrayVisible
		{
			get
			{
				return settingsService.GetSetting(SystemTrayVisibleKey, systemTrayVisibleDefaultValue);
			}
			set
			{
				settingsService.SetSetting(SystemTrayVisibleKey, value);
			}
		}

		const string ConfirmAppClose = "ConfirmAppExit";
		static bool confirmAppCloseDefaultValue = false;

		public bool ConfirmAppExit
		{
			get
			{
				return settingsService.GetSetting(ConfirmAppClose, true);
			}
			set
			{
				settingsService.SetSetting(ConfirmAppClose, value);
			}
		}

		/* Use the following template for new settings. */
		//	const string mySettingKey = "MySetting";
		//  static string mySettingDefaultValue = "example";
		//
		//	public string MySetting
		//	{
		//		get
		//		{
		//			return settingsService.GetSetting(mySettingKey, mySettingDefaultValue);
		//		}
		//		set
		//		{
		//			settingsService.SetSetting(mySettingKey, value);
		//		}
		//	}

		#region Singleton implementation

		static readonly AppSettings instance = new AppSettings();

		AppSettings()
		{
			var messageBus = Dependency.Resolve<IMessenger>();
			messageBus.Subscribe(this);
		}

		public static AppSettings Instance
		{
			get
			{
				return instance;
			}
		}

		#endregion

		/// <summary>
		/// Receives the settings changed message from the message bus.
		/// We signal that the setting has changed by using the convention 
		/// that the property name is the setting name.
		/// </summary>
		/// <param name="message">The <see cref="Outcoder.Services.SettingChangeEventArgs"/> 
		/// instance containing the event data.</param>
		Task IMessageSubscriber<SettingChangeEventArgs>.ReceiveMessage(SettingChangeEventArgs message)
		{
			OnPropertyChanged(message.SettingName);

			return Task.FromResult(0);
		}
	}
}
